package com.qf.web.common.ascpet;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qf.common.base.exception.ServiceException;
import com.qf.common.base.result.ResponseResult;
import com.qf.common.base.result.ResultCode;
import com.qf.web.common.annotations.CacheParam;
import com.qf.web.common.annotations.EnableRedisCache;
import com.qf.web.common.utils.RedisKeyUtils;
import com.qf.web.dao.BaseRedisDao;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

/**
 * 用于当查询商品、店铺商品、店铺套餐时缓存
 * @author 谢积威
 */
@Aspect
@Component
public class RedisCacheAspect {

    @Autowired
    BaseRedisDao baseRedisDao;

    /**
     * 定义切点
     */
    @Pointcut("@annotation(com.qf.web.common.annotations.EnableRedisCache)")
    public void pointCut(){

    }

    /**
     * 定义环绕通知
     * @param joinPoint
     * @return
     */
    @Around("pointCut()")
    public Object around(ProceedingJoinPoint joinPoint){
        Object obj = null;
        //redis中key的设计 注解中传递key的前缀+ID值
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        EnableRedisCache enableRedisCache = method.getAnnotation(EnableRedisCache.class);
        //获取Key
        String key = RedisKeyUtils.getCacheKey(method,joinPoint.getArgs(),enableRedisCache.keyPrefix());
        //通过key去redis中看看是否存在缓存
        String cache = (String) baseRedisDao.getForValue(key);
        if (!ObjectUtils.isEmpty(cache)){
            //如果存在缓存，处理缓存，直接返回，不再去数据库中查找
            //对缓存进行处理
            ResponseResult result = null;
            try {
                result = new ObjectMapper().readValue(cache, ResponseResult.class);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            return result;
        }
        //缓存中不存在，去数据库中查询
        try {
            obj = joinPoint.proceed();
        } catch (Throwable e) {
            throw new ServiceException(ResultCode.BUSINESS_UNKNOW_ERROR);
        }
        ResponseResult result = (ResponseResult) obj;
        //查询完，在返回之前先存到redis中
        String json = null;
        try {
            json = new ObjectMapper().writeValueAsString(result);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        baseRedisDao.setForValue(key,json,enableRedisCache.timeout(),enableRedisCache.timeUnit());
        return obj;
    }

}
